import { AppType, PlayerProps, playerOrderType } from '@/Util/Constant';
import { PixiBase } from '@/game/baseClass/PixiBase';
import { Broadcaster, DataChange, EventType } from '@/game/broadcaster/Broadcaster';
import Hlddz from '@/game/model/hlddz';
import { Player } from './player';
import * as PIXI from 'pixi.js'
import { GameStatus, OutCardType, PlayerType, SocketDataType, SocketEventType, SummaryObjType } from '@/share/commonType';
import { UserAsset } from '../userAsset';
import { getUserInfo } from '@/Util';
import { Button } from '../button/button';
import socket from '@/socket/UserChatSocket';
let TextureCache = PIXI.utils.TextureCache

export class PlayerController extends PixiBase {
    model: Hlddz = Hlddz.getInstance();
    private prepareIcon: PIXI.Sprite;
    myname: string = getUserInfo().username;
    userAsset: UserAsset;
    prepareButton: Button;
    beforePlayerName: string;
    afterPlayerName: string;
    beforePlayerInfo: PlayerType;
    afterPlayerInfo: PlayerType;
    beforePlayer: Player;
    afterPlayer: Player;
    doubleNum: PIXI.Text;
    constructor(public app: AppType) {
        super(app)
        this.addListener(this.model)
    }
    initMyAssetInfo() {// 初始化左上角当前玩家的信息
        this.userAsset = new UserAsset({
            baseContainer: this.baseContainer,
            scale: this.scaleSize
        })
        let playerinfo = this.model.getPlayerInfo(this.myname)
        this.userAsset.setUser(playerinfo.nickname, new PIXI.Sprite(TextureCache['avatar']))
        this.userAsset.setHldNum(playerinfo.hld)
    }

    updatePlayer() {
        let { beforePlayer, afterPlayer } = this.model.getBeforeAndAfterPlayer()
        this.beforePlayerName = beforePlayer
        this.afterPlayerName = afterPlayer
        this.beforePlayerInfo = this.model.getPlayerInfo(this.beforePlayerName)
        this.afterPlayerInfo = this.model.getPlayerInfo(this.afterPlayerName)
    }

    initDoubleNum() {
        if (this.model.gameStatus !== GameStatus.Gaming) return;
        let doubleSprite = new PIXI.Sprite(TextureCache['double'])
        this.doubleNum = new PIXI.Text(this.model.multiple, {
            fontFamily: "微软雅黑",
            fill: '#f4e9a8',
            fontSize: 30,
            align: "left",
            dropShadow: true,
            fontWeight: 'bold',
            dropShadowColor: "#f7c258",
            dropShadowBlur: 3,
            dropShadowAngle: Math.PI / 2,
            dropShadowDistance: 2,
        }) as PIXI.Text;
        this.doubleNum.x = 55
        this.doubleNum.y = 8
        doubleSprite.addChild(this.doubleNum)
        doubleSprite.scale.set(this.scaleSize * 0.7)
        doubleSprite.x = window.innerWidth * 0.15
        doubleSprite.y = window.innerHeight - doubleSprite.height + 2 * this.scaleSize
        this.baseContainer.addChild(doubleSprite)
    }

    updateDoubleNum() {
        if (this.model.gameStatus !== GameStatus.Gaming) return;
        this.doubleNum.text = this.model.multiple
    }

    initPlayer() {
        this.beforePlayer = new Player(Object.assign({
            playerName: '',
            playerOrder: playerOrderType.Before,
            playerSprite: new PIXI.Sprite(TextureCache['gril-l']),
            posX: 0,
            posY: window.innerHeight * 0.35,
        }, { baseContainer: this.baseContainer }))
        this.afterPlayer = new Player(Object.assign({
            playerName: '',
            playerOrder: playerOrderType.After,
            playerSprite: new PIXI.Sprite(TextureCache['gril-r']),
            posX: window.innerWidth * 0.78,
            posY: window.innerHeight * 0.35,
        }, { baseContainer: this.baseContainer }))
    }

    renderPlayer() {
        this.beforePlayer.setPlayer(this.beforePlayerName, this.model)
        this.afterPlayer.setPlayer(this.afterPlayerName, this.model)
    }

    renderCard() {
        let cardInfo = this.model.lastOutCardInfo?.outCardInfo
        let playerName = this.model.lastOutCardInfo.playerName
        if (playerName === this.beforePlayerName && cardInfo?.type !== OutCardType.EMPTY_CARD_FLAG) {
            this.beforePlayer.renderCard(cardInfo?.rawCards)
        }
        if (playerName === this.afterPlayerName && cardInfo?.type !== OutCardType.EMPTY_CARD_FLAG) {
            this.afterPlayer.renderCard(cardInfo?.rawCards)
        }
    }

    renderLandlord() {
        if (this.model.gameStatus !== GameStatus.Gaming) return;
        let landlord = this.model.landlord
        if (landlord === this.beforePlayerName) {
            this.beforePlayer.renderLandlord()
        }
        if (landlord === this.afterPlayerName) {
            this.afterPlayer.renderLandlord()
        }
    }

    loadPrepareIcon() {
        this.prepareIcon = new PIXI.Sprite(TextureCache['ok'])
        this.prepareIcon.scale.set(this.scaleSize)
        this.baseContainer.addChild(this.prepareIcon)
        this.showPrepareIcon()
    }

    showPrepareIcon() {
        if (this.model.gameStatus !== GameStatus.Wait) {
            this.prepareIcon.visible = false
            return;
        };
        let playerInfo = this.model.getPlayerInfo(this.myname)
        this.prepareIcon.visible = playerInfo.status
        this.prepareIcon.x = 250 * this.scaleSize
        this.prepareIcon.y = window.innerHeight - 200 * this.scaleSize
    }

    renderPrepareButton() {
        if (this.model.gameStatus !== GameStatus.Wait) {
            this.prepareButton && this.prepareButton.hidden()
            return;
        };
        let playerInfo = this.model.getPlayerInfo(this.myname)
        const prepareButtonContainer = new PIXI.Container()
        this.prepareButton = new Button({
            container: prepareButtonContainer,
            text: playerInfo.status ? '取消准备' : '准备',
            bgColor: '#68bceb',
            width: 150,
            handler: this.prepareHandler,
            scaleSize: this.scaleSize
        })
        prepareButtonContainer.x = (window.innerWidth - 150 * this.scaleSize) / 2
        prepareButtonContainer.y = window.innerHeight - 150 * this.scaleSize
        this.baseContainer.addChild(prepareButtonContainer)
    }

    prepareHandler = () => {
        let playerInfo = this.model.getPlayerInfo(this.myname)
        playerInfo.status = !playerInfo.status
        this.prepareButton.setButtonText(playerInfo.status ? '取消准备' : '准备')
        this.showPrepareIcon()
        socket.emit({
            action: SocketEventType.DdzGame,
            dataType: SocketDataType.ChangeStatus,
            data: {
                username: this.myname,
                gameId: this.model.gameId,
            }
        })
    }

    renderCardNum() {
        if (this.model.gameStatus !== GameStatus.Gaming) return;
        this.beforePlayer.renderCardNum()
        this.afterPlayer.renderCardNum()
    }

    updateCardNum() {
        if (this.model.gameStatus !== GameStatus.Gaming) return;
        let cardNum = this.model.cardNum
        this.beforePlayer.setCardNumber(cardNum[this.beforePlayerName].toString())
        this.afterPlayer.setCardNumber(cardNum[this.afterPlayerName].toString())
    }

    renderPrepareIcon() {
        if (this.model.gameStatus === GameStatus.Gaming) {
            this.beforePlayer.showPrepareIcon(false)
            this.afterPlayer.showPrepareIcon(false)
            return;
        }
        this.beforePlayer.showPrepareIcon(this.beforePlayerInfo?.status)
        this.afterPlayer.showPrepareIcon(this.afterPlayerInfo?.status)
    }

    loadRenderCard() {
        if (this.model.gameStatus !== GameStatus.Gaming) return;
        if (!this.model.isCompleteDouble) return;
        let outCardList = this.model.outCardList
        if (!outCardList) return;
        if (outCardList[this.beforePlayerName]?.type !== OutCardType.EMPTY_CARD_FLAG) this.beforePlayer.renderCard(outCardList[this.beforePlayerName]?.rawCards);
        if (outCardList[this.afterPlayerName]?.type !== OutCardType.EMPTY_CARD_FLAG) this.afterPlayer.renderCard(outCardList[this.afterPlayerName]?.rawCards);
    }

    updateHldNum(summaryObj: SummaryObjType) {
        for (const [name, summary] of Object.entries(summaryObj)) {
            let hld = summary.resHld;
            if (name === this.myname) {
                this.userAsset.setHldNum(hld)
            } else if (name === this.beforePlayerName) {
                this.beforePlayer.setHldNum(hld)
            } else {
                this.afterPlayer.setHldNum(hld)
            }
        }
    }
    showTimer() {
        if (this.model.gameStatus !== GameStatus.Gaming) return;
        let nowOutCardPlayer = this.model.nowOutCardPlayer
        this.beforePlayer.hiddenTimer()
        this.afterPlayer.hiddenTimer()
        if (nowOutCardPlayer === this.beforePlayerName) {
            this.beforePlayer.showTimer()
        }
        if (nowOutCardPlayer === this.afterPlayerName) {
            this.afterPlayer.showTimer()
        }
    }

    gameRestart() { // 开始下一局游戏
        // 清除元素
        this.beforePlayer.gameRestart()
        this.afterPlayer.gameRestart()
        this.renderPlayer()
        this.renderPrepareIcon()
        this.renderPrepareButton()
        this.loadPrepareIcon()
    }

    notify(caster: Broadcaster, event: EventType): void {
        let action = event.action
        this.updatePlayer()
        switch (action) {
            case DataChange.FinishLoad:
                this.initPlayer()
                this.renderPlayer()
                this.renderLandlord()
                this.renderCardNum()
                this.updateCardNum()
                this.loadRenderCard()
                this.initMyAssetInfo()
                this.initDoubleNum()
                this.renderPrepareIcon()
                this.renderPrepareButton()
                this.loadPrepareIcon()
                this.showTimer()
                break;
            case DataChange.GameStart:
                this.renderLandlord()
                this.initDoubleNum()
                this.renderCardNum()
                this.updateCardNum()
                this.renderPrepareButton()
                this.renderPrepareIcon()
                this.showPrepareIcon()
                this.showTimer()
                break;
            case DataChange.Double:
                this.updateDoubleNum()
                break;
            case DataChange.PlayerChange:
                this.renderPlayer()
                this.renderPrepareIcon()
                break;
            case DataChange.OutCard:
                this.renderCard()
                this.updateCardNum()
                this.showTimer()
                break;
            case DataChange.GameOver:
                this.updateHldNum(event.data)
                break;
            case DataChange.Restart:
                this.gameRestart()
                break;
            default:
                break;
        }
    }

}